home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2001 May / may_2001.iso / intercd / root / Multimedia / ^DivX_Article / virtualdub / VirtualDub-source-1_4d / Setup / main.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-02-01  |  34.6 KB  |  1,180 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stddef.h>
  4. #include <stdarg.h>
  5. #include <malloc.h>
  6. #include <ctype.h>
  7. #include <crtdbg.h>
  8.  
  9. #include <windows.h>
  10. #include <commctrl.h>
  11.  
  12. #include "resource.h"
  13. #include "registry.h"
  14. #include "help.h"
  15. #include "helpfile.h"
  16.  
  17. HWND g_hwnd;
  18. HINSTANCE g_hInst; // current instance
  19. char szAppName[] = "VirtualDub Setup Class"; // The name of this application
  20. char szTitle[]   = ""; // The title bar text
  21. char g_szWinPath[MAX_PATH];
  22. char g_szProgPath[MAX_PATH];
  23. char g_szTempPath[MAX_PATH];
  24.  
  25. ///////////////////
  26.  
  27. BOOL Init(HINSTANCE, int);
  28. LRESULT APIENTRY WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
  29.  
  30. BOOL APIENTRY InstallAVIFileDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
  31. BOOL APIENTRY UninstallAVIFileDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
  32. BOOL APIENTRY RemoveSettingsDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
  33. BOOL APIENTRY DiskTestDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
  34. BOOL APIENTRY AboutDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
  35.  
  36. ///////////
  37.  
  38. int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
  39.     LPSTR lpCmdLine, int nCmdShow )
  40. {
  41.     MSG msg;
  42.     char *lpszFilePart;
  43.  
  44.     ///////////
  45.  
  46.     if (!GetWindowsDirectory(g_szWinPath, sizeof g_szWinPath)) return FALSE;
  47.     if (!GetModuleFileName(NULL, g_szTempPath, sizeof g_szTempPath))
  48.         return FALSE;
  49.     if (!GetFullPathName(g_szTempPath, sizeof g_szProgPath, g_szProgPath, &lpszFilePart))
  50.         return FALSE;
  51.     *lpszFilePart=0;
  52.  
  53.     HelpSetPath();
  54.  
  55.     if (!Init(hInstance, nCmdShow)) return FALSE;
  56.  
  57.     // Main message loop.
  58.  
  59.     while (GetMessage(&msg, NULL, 0, 0)) {
  60. //        if (!IsDialogMessage(g_hwnd, &msg))
  61.         TranslateMessage(&msg);
  62.         DispatchMessage(&msg);
  63.     }
  64.  
  65.     return 0;
  66. }
  67.  
  68. ////////////////
  69.  
  70. BOOL Init(HINSTANCE hInstance, int nCmdShow)
  71. {
  72.     WNDCLASS  wc;
  73.  
  74.     // Register the window class for my window.                                                           */
  75.     wc.style = 0;                       // Class style.
  76.     wc.lpfnWndProc = (WNDPROC)WndProc; // Window procedure for this class.
  77.     wc.cbClsExtra = 0;                  // No per-class extra data.
  78.     wc.cbWndExtra = DLGWINDOWEXTRA;                  // No per-window extra data.
  79.     wc.hInstance = hInstance;           // Application that owns the class.
  80.     wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  81.     wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  82.     wc.hbrBackground = (HBRUSH)(COLOR_3DFACE+1); 
  83.     wc.lpszMenuName =  NULL;   // Name of menu resource in .RC file. 
  84.     wc.lpszClassName = szAppName; // Name used in call to CreateWindow.
  85.  
  86.     if (!RegisterClass(&wc)) return FALSE;
  87.  
  88.     g_hInst = hInstance; // Store instance handle in our global variable
  89.  
  90.     g_hwnd = CreateDialog(hInstance,MAKEINTRESOURCE(IDD_MAINWINDOW),NULL,(DLGPROC)NULL);
  91.  
  92.     if (!g_hwnd) {
  93.         return (FALSE);
  94.     }
  95.  
  96.     ShowWindow(g_hwnd, nCmdShow);
  97.     UpdateWindow(g_hwnd);
  98.  
  99.     return (TRUE);
  100. }
  101.  
  102. void PrintfWindowText(HWND hWnd, char *format, ...) {
  103.     char buf[256];
  104.     va_list val;
  105.  
  106.     va_start(val, format);
  107.     vsprintf(buf, format, val);
  108.     va_end(val);
  109.     SetWindowText(hWnd, buf);
  110. }
  111.  
  112. DWORD dwMainWindowHelpLookup[]={
  113.     IDC_BENCHMARK,        IDH_SETUP_BENCHMARK,
  114.     IDC_INSTALL,        IDH_SETUP_INSTALL,
  115.     IDC_UNINSTALL,        IDH_SETUP_UNINSTALL,
  116.     IDC_REMOVE,            IDH_SETUP_REMOVE,
  117.     0
  118. };
  119.  
  120. LRESULT APIENTRY WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  121. {
  122.  
  123.     switch (message) { 
  124.         case WM_DESTROY:
  125.             PostQuitMessage(0);
  126.             break;
  127.  
  128.         case WM_COMMAND:
  129.             switch(LOWORD(wParam)) {
  130.             case IDC_EXECUTE:
  131.                 if ((int)ShellExecute(hWnd, "open", "VirtualDub.exe", NULL, NULL, SW_SHOWNORMAL) <= 32)
  132.                     MessageBox(hWnd, "Couldn't launch VirtualDub.exe.", "Oops", MB_OK);
  133.                 break;
  134.             case IDC_BENCHMARK:
  135.                 DialogBox(g_hInst, MAKEINTRESOURCE(IDD_DISKTEST_SETUP), hWnd, (DLGPROC)DiskTestDlgProc);
  136.                 break;
  137.             case IDC_INSTALL:
  138.                 DialogBox(g_hInst, MAKEINTRESOURCE(IDD_ATTEMPT), hWnd, (DLGPROC)InstallAVIFileDlgProc);
  139.                 break;
  140.             case IDC_UNINSTALL:
  141.                 DialogBox(g_hInst, MAKEINTRESOURCE(IDD_ATTEMPT), hWnd, (DLGPROC)UninstallAVIFileDlgProc);
  142.                 break;
  143.             case IDC_REMOVE:
  144.                 DialogBox(g_hInst, MAKEINTRESOURCE(IDD_ATTEMPT), hWnd, (DLGPROC)RemoveSettingsDlgProc);
  145.                 break;
  146.             case IDC_ABOUT:
  147.                 DialogBox(g_hInst, MAKEINTRESOURCE(IDD_ABOUT), hWnd, (DLGPROC)AboutDlgProc);
  148.                 break;
  149.             case IDCANCEL:
  150.                 DestroyWindow(hWnd);
  151.                 break;
  152.             }
  153.             break;
  154.  
  155.         case WM_HELP:
  156.             {
  157.                 HELPINFO *lphi = (HELPINFO *)lParam;
  158.  
  159.                 if (lphi->iContextType == HELPINFO_WINDOW)
  160.                     HelpPopupByID(hWnd, lphi->iCtrlId, dwMainWindowHelpLookup);
  161.             }
  162.             return TRUE;
  163.  
  164.         default:
  165.             return DefWindowProc(hWnd,message,wParam,lParam);
  166.     }
  167.     return (0);
  168. }
  169.  
  170. //////////////////////////////////////////////////////////////////////
  171.  
  172. void ListboxAddf(HWND hwndListbox, char *format, ...) {
  173.     char buf[256];
  174.     va_list val;
  175.  
  176.     va_start(val, format);
  177.     _vsnprintf(buf, sizeof buf, format, val);
  178.     va_end(val);
  179.     buf[(sizeof buf) - 1] = 0;
  180.  
  181.     SendMessage(hwndListbox, LB_ADDSTRING, 0, (LPARAM)buf);
  182. }
  183.  
  184. BOOL InstallFile(char *szSource, char *szDestFormat, ...) {
  185.     char szDest[MAX_PATH];
  186.     char szSourcePath[MAX_PATH];
  187.     char szDestPath[MAX_PATH];
  188.     char szDestFile[MAX_PATH];
  189.     char *lpszDestFile;
  190.     char szCurInst[MAX_PATH];
  191.     char szTempFile[MAX_PATH];
  192.     DWORD dwFlags = VIFF_DONTDELETEOLD;
  193.     DWORD dwRet;
  194.     UINT uTmpLen;
  195.     char szFailure[256];
  196.     va_list val;
  197.  
  198.     va_start(val, szDestFormat);
  199.     vsprintf(szDest, szDestFormat, val);
  200.     va_end(val);
  201.  
  202.     if (!GetFullPathName(szDest, sizeof szDestPath, szDestPath, &lpszDestFile))
  203.         return FALSE;
  204.  
  205.     strcpy(szDestFile, lpszDestFile);
  206.     *lpszDestFile=0;
  207.  
  208.     do {
  209.         szTempFile[0]=0;
  210.         szCurInst[0]=0;
  211.         uTmpLen = sizeof szTempFile;
  212.         dwRet = VerInstallFile(dwFlags, szSource, szDestFile, g_szProgPath, szDestPath, szCurInst, szTempFile, &uTmpLen);
  213.  
  214.         if (dwRet & VIF_TEMPFILE) {
  215.             DeleteFile(szTempFile);
  216.             dwRet &= ~VIF_TEMPFILE;
  217.         }
  218.  
  219.         szFailure[0]=0;
  220.  
  221.         if (dwRet & (VIF_MISMATCH | VIF_DIFFTYPE))
  222.             sprintf(szFailure,    "The old %s doesn't look like a VirtualDub file.\n"
  223.                                 "If it belongs to another application, installing the new file may cause "
  224.                                 "the other app to stop functioning.\n"
  225.                                 "Install the new file only if you are sure or have a backup."
  226.                                 ,szDestFile);
  227.         else if (dwRet & VIF_SRCOLD)
  228.             sprintf(szFailure,    "%s is older than the %s being installed over.\n"
  229.                                 "You should install the older %s if you do not use other versions "
  230.                                 "of VirtualDub, since the newer file may be incompatible."
  231.                                 ,szSource,szDestFile);
  232.         else if (dwRet & VIF_WRITEPROT)
  233.             sprintf(szFailure,    "The %s being installed over has been marked read-only.\n"
  234.                                 "Override read-only attribute and install anyway?"
  235.                                 ,szDestFile);
  236.         else if (dwRet & VIF_FILEINUSE)
  237.             sprintf(szFailure,    "%s is in use.  It cannot be installed over right now.\n"
  238.                                 "If you have any copies of VirtualDub or any programs that "
  239.                                 "may be using VirtualDub's AVIFile handler, please close them "
  240.                                 "and then click OK to retry the operation."
  241.                                 ,szDestFile);
  242.         else if (dwRet & VIF_OUTOFSPACE)
  243.             sprintf(szFailure,    "Doh! We're out of space trying to write:\n\t%s\n\nCan you clear some up?"
  244.                                 ,szDest);
  245.         else if (dwRet & VIF_ACCESSVIOLATION)
  246.             sprintf(szFailure,    "Access violation.  Check with your administrator to see if you have "
  247.                                 "the appropriate permissions to write to \"%s\"."
  248.                                 ,szDest);
  249.         else if (dwRet & VIF_SHARINGVIOLATION)
  250.             sprintf(szFailure,    "Share violation; something else probably has %s open.  Try closing applications that "
  251.                                 "have the file open, and check permissions on network drives."
  252.                                 ,szDestFile);
  253.         else if (dwRet & VIF_CANNOTCREATE)
  254.             sprintf(szFailure,    "Couldn't create temporary file %s.\nTry again?", szTempFile);
  255.         else if (dwRet & VIF_CANNOTDELETE)
  256.             sprintf(szFailure,    "Couldn't delete temporary file %s.\nTry installing again?", szTempFile);
  257.         else if (dwRet & VIF_CANNOTDELETECUR)
  258.             sprintf(szFailure,    "Couldn't delete existing file \"%s\".\nTry installing again?", szDest);
  259.         else if (dwRet & VIF_CANNOTRENAME)
  260.             sprintf(szFailure,    "Deleted old file %s, but couldn't move %s into its place.\n"
  261.                                 "You should retry this operation.", szDestFile, szSource);
  262.         else if (dwRet & VIF_CANNOTREADSRC)
  263.             sprintf(szFailure,    "Couldn't read source file \"%s\".  Should I try again?"
  264.                                 ,szSource);
  265.         else if (dwRet & VIF_CANNOTREADDST)
  266.             sprintf(szFailure,    "Couldn't read destination file \"%s\".  I can try installing over it "
  267.                                 "anyway, though."
  268.                                 ,szDest);
  269.         else if (dwRet & VIF_OUTOFMEMORY)
  270.             sprintf(szFailure,    "Ran out of memory!  Try freeing some up.");
  271.         else if (dwRet)
  272.             sprintf(szFailure,    "Unidentified error copying:\n\t%s\n\t\tto\n\t%s\n\nTry forcing install?"
  273.                                 ,szSource
  274.                                 ,szDest);
  275.  
  276.         if (szFailure[0])
  277.             if (IDNO==MessageBox(NULL, szFailure, "Install error", MB_YESNO | MB_APPLMODAL))
  278.                 return FALSE;
  279.  
  280.         dwFlags |= VIFF_FORCEINSTALL;
  281.     } while(dwRet);
  282.  
  283.     return TRUE;
  284. }
  285.  
  286. BOOL InstallRegStr(HKEY hkBase, char *szKeyName, char *szName, char *szValue) {
  287.     char buf[256];
  288.  
  289.     if (!SetRegString(hkBase, szKeyName, szName, szValue)) {
  290.         sprintf(buf,"Couldn't set registry key %s\\%s",szKeyName,szName?szName:"(default)");
  291.         MessageBox(NULL, buf, "Install error", MB_OK);
  292.         return FALSE;
  293.     }
  294.  
  295.     return TRUE;
  296. }
  297.  
  298. BOOL InstallDeleteFile(char *szFileFormat, ...) {
  299.     char szFile[256];
  300.     va_list val;
  301.  
  302.     va_start(val, szFileFormat);
  303.     vsprintf(szFile, szFileFormat, val);
  304.     va_end(val);
  305.  
  306.     if (!DeleteFile(szFile))
  307.         if (GetLastError() != ERROR_FILE_NOT_FOUND)
  308.             return FALSE;
  309.  
  310.     return TRUE;
  311. }
  312.  
  313.  
  314. ///////////////////////////////////////
  315.  
  316. BOOL APIENTRY InstallAVIFileDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
  317.     switch(msg) {
  318.         case WM_INITDIALOG:
  319.             {
  320.                 HWND hwndListbox = GetDlgItem(hDlg, IDC_ACTIONLIST);
  321.  
  322.                 SetWindowText(hDlg, "Install AVIFile frameclient");
  323.  
  324.                 ListboxAddf(hwndListbox, "Copy VDREMOTE.DLL to %s\\SYSTEM\\VDREMOTE.DLL", g_szWinPath);
  325.                 ListboxAddf(hwndListbox, "Copy VDSRVLNK.DLL to %s\\SYSTEM\\VDSRVLNK.DLL", g_szWinPath);
  326.                 ListboxAddf(hwndListbox, "Add VDRemote class and AVIFile entries to Registry");
  327.             }
  328.             return TRUE;
  329.  
  330.         case WM_COMMAND:
  331.             switch(LOWORD(wParam)) {
  332.             case IDOK:
  333.                 if (    InstallFile("vdremote.dll","%s\\system\\vdremote.dll",g_szWinPath)
  334.                     &&    InstallFile("vdsvrlnk.dll","%s\\system\\vdsvrlnk.dll",g_szWinPath)
  335.                     &&    InstallRegStr(HKEY_CLASSES_ROOT,"CLSID\\{894288e0-0948-11d2-8109-004845000eb5}",NULL,"VirtualDub link handler")
  336.                     &&    InstallRegStr(HKEY_CLASSES_ROOT,"CLSID\\{894288e0-0948-11d2-8109-004845000eb5}\\InprocServer32",NULL,"vdremote.dll")
  337.                     &&    InstallRegStr(HKEY_CLASSES_ROOT,"CLSID\\{894288e0-0948-11d2-8109-004845000eb5}\\InprocServer32","ThreadingModel","Apartment")
  338.                     &&    InstallRegStr(HKEY_CLASSES_ROOT,"CLSID\\{894288e0-0948-11d2-8109-004845000eb5}\\InprocServer32\\AVIFile",NULL,"1")
  339.                     &&    InstallRegStr(HKEY_CLASSES_ROOT,"AVIFile\\Extensions\\VDR",NULL,"{894288e0-0948-11d2-8109-004845000eb5}")
  340.                     &&    InstallRegStr(HKEY_CLASSES_ROOT,"AVIFile\\RIFFHandlers\\VDRM",NULL,"{894288e0-0948-11d2-8109-004845000eb5}")
  341.                     )
  342.  
  343.                     MessageBox(hDlg, "AVIFile frameclient install successful.", "VirtualDub Setup", MB_OK);
  344.                 else
  345.                     MessageBox(hDlg, "AVIFile frameclient install failed.", "VirtualDub Setup", MB_OK);
  346.  
  347.                 EndDialog(hDlg, TRUE);
  348.                 return TRUE;
  349.             case IDCANCEL:
  350.                 EndDialog(hDlg, FALSE);
  351.                 return TRUE;
  352.             }
  353.     }
  354.     return FALSE;
  355. }
  356.  
  357. BOOL APIENTRY UninstallAVIFileDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
  358.     BOOL fSuccess;
  359.  
  360.     switch(msg) {
  361.         case WM_INITDIALOG:
  362.             {
  363.                 HWND hwndListbox = GetDlgItem(hDlg, IDC_ACTIONLIST);
  364.  
  365.                 SetWindowText(hDlg, "Uninstall AVIFile frameclient");
  366.  
  367.                 ListboxAddf(hwndListbox, "Delete %s\\SYSTEM\\VDREMOTE.DLL", g_szWinPath);
  368.                 ListboxAddf(hwndListbox, "Delete %s\\SYSTEM\\VDSRVLNK.DLL", g_szWinPath);
  369.                 ListboxAddf(hwndListbox, "Remove VDRemote class and AVIFile entries from Registry");
  370.             }
  371.             return TRUE;
  372.  
  373.         case WM_COMMAND:
  374.             switch(LOWORD(wParam)) {
  375.             case IDOK:
  376.                 fSuccess =  InstallDeleteFile("%s\\system\\vdremote.dll",g_szWinPath);
  377.                 fSuccess &= InstallDeleteFile("%s\\system\\vdsvrlnk.dll",g_szWinPath);
  378.  
  379.                 if (    ERROR_SUCCESS != RegDeleteKey(HKEY_CLASSES_ROOT,"Clsid\\{894288e0-0948-11d2-8109-004845000eb5}\\InprocServer32\\AVIFile")
  380.                     ||    ERROR_SUCCESS != RegDeleteKey(HKEY_CLASSES_ROOT,"Clsid\\{894288e0-0948-11d2-8109-004845000eb5}\\InprocServer32")
  381.                     ||    ERROR_SUCCESS != RegDeleteKey(HKEY_CLASSES_ROOT,"Clsid\\{894288e0-0948-11d2-8109-004845000eb5}")
  382.                     ||    ERROR_SUCCESS != RegDeleteKey(HKEY_CLASSES_ROOT,"AVIFile\\Extensions\\VDR")
  383.                     ||    ERROR_SUCCESS != RegDeleteKey(HKEY_CLASSES_ROOT,"AVIFile\\RIFFHandlers\\VDRM"))
  384.  
  385.                     MessageBox(hDlg, "Registry entries were in use.  Deinstall not successful.\n"
  386.                                     "\n"
  387.                                     "A partial installation now exists on your system.  Reinstall the AVIFile "
  388.                                     "handler to restore frameclient functionality, or close applications that may "
  389.                                     "be occupying the Registry entries and retry the deinstall."
  390.                                     ,"VirtualDub Setup",MB_OK);
  391.  
  392.                 else if (!fSuccess)
  393.                     MessageBox(hDlg, "DLL files were in use.  Deinstall not successful.\n"
  394.                                     "\n"
  395.                                     "A partial installation now exists on your system.  Reinstall the AVIFile "
  396.                                     "handler to restore frameclient functionality, or close applications that may "
  397.                                     "be occupying the shared DLLs and retry the deinstall."
  398.                                     ,"VirtualDub Setup",MB_OK);
  399.                 else
  400.                     MessageBox(hDlg, "AVIFile frameclient deinstall successful.", "VirtualDub Setup", MB_OK);
  401.  
  402.                 EndDialog(hDlg, TRUE);
  403.                 return TRUE;
  404.             case IDCANCEL:
  405.                 EndDialog(hDlg, FALSE);
  406.                 return TRUE;
  407.             }
  408.     }
  409.     return FALSE;
  410. }
  411.  
  412. ///////////////////////////////////////////////
  413.  
  414. void RemoveVirtualDubKeys(HWND hwndListbox) {
  415.     FILETIME ftModified;
  416.     int i;
  417.     LONG err;
  418.     char szKeyName[MAX_PATH];
  419.     char szErrorText[128];
  420.     DWORD dwKeyNameLen;
  421.  
  422.     SendMessage(hwndListbox, LB_RESETCONTENT, 0, 0);
  423.  
  424.     i=0;
  425.     for(;;) {
  426.         dwKeyNameLen = sizeof szKeyName;
  427.         err = RegEnumKeyEx(HKEY_USERS, i++, szKeyName, &dwKeyNameLen, 0, NULL, 0, &ftModified);
  428.  
  429.         if (err == ERROR_NO_MORE_ITEMS)
  430.             break;
  431.         else if (err == ERROR_SUCCESS) {
  432.             HKEY hkeyUser;
  433.             char *bp = szKeyName + strlen(szKeyName);
  434.             
  435.             err = RegOpenKeyEx(HKEY_USERS, szKeyName, 0, KEY_ALL_ACCESS, &hkeyUser);
  436.             if (err != ERROR_SUCCESS) {
  437.                 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, szErrorText, sizeof szErrorText, NULL);
  438.                 ListboxAddf(hwndListbox, "HKEY_USERS\\%s: %s", szKeyName, szErrorText);
  439.                 continue;
  440.             }
  441.  
  442.             strcpy(bp, "\\Software\\Freeware\\VirtualDub\\Capture");
  443.  
  444.             err = RegDeleteKey(HKEY_CLASSES_ROOT,szKeyName);
  445.             if (err != ERROR_SUCCESS)
  446.                 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, szErrorText, sizeof szErrorText, NULL);
  447.             else
  448.                 strcpy(szErrorText, "Deleted");
  449.             ListboxAddf(hwndListbox, "HKEY_USERS\\%s: %s", szKeyName, szErrorText);
  450.  
  451.             strcpy(bp, "\\Software\\Freeware\\VirtualDub\\MRUList");
  452.  
  453.             err = RegDeleteKey(HKEY_CLASSES_ROOT,szKeyName);
  454.             if (err != ERROR_SUCCESS)
  455.                 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, szErrorText, sizeof szErrorText, NULL);
  456.             else
  457.                 strcpy(szErrorText, "Deleted");
  458.             ListboxAddf(hwndListbox, "HKEY_USERS\\%s: %s", szKeyName, szErrorText);
  459.  
  460.             bp[29]=0;
  461.  
  462.             err = RegDeleteKey(HKEY_CLASSES_ROOT,szKeyName);
  463.             if (err != ERROR_SUCCESS)
  464.                 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, szErrorText, sizeof szErrorText, NULL);
  465.             else
  466.                 strcpy(szErrorText, "Deleted");
  467.             ListboxAddf(hwndListbox, "HKEY_USERS\\%s: %s", szKeyName, szErrorText);
  468.  
  469.             RegCloseKey(hkeyUser);
  470.         }
  471.     }
  472. }
  473.  
  474. BOOL APIENTRY RemoveSettingsDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
  475.     BOOL fSuccess;
  476.  
  477.     switch(msg) {
  478.         case WM_INITDIALOG:
  479.             {
  480.                 HWND hwndListbox = GetDlgItem(hDlg, IDC_ACTIONLIST);
  481.  
  482.                 SetWindowText(hDlg, "Remove VirtualDub preference data");
  483.  
  484.                 ListboxAddf(hwndListbox, "Remove HKEY_USERS\\*\\Software\\Freeware\\VirtualDub\\*");
  485.             }
  486.             return TRUE;
  487.  
  488.         case WM_COMMAND:
  489.             switch(LOWORD(wParam)) {
  490.             case IDOK:
  491.                 SetWindowText(GetDlgItem(hDlg, IDC_ACTION), "Results:");
  492.  
  493.                 RemoveVirtualDubKeys(GetDlgItem(hDlg, IDC_ACTIONLIST));
  494.  
  495.                 SetWindowText(GetDlgItem(hDlg, IDOK), "Retry");
  496.                 SetWindowText(GetDlgItem(hDlg, IDCANCEL), "Done");
  497.                 return TRUE;
  498.             case IDCANCEL:
  499.                 EndDialog(hDlg, FALSE);
  500.                 return TRUE;
  501.             }
  502.     }
  503.     return FALSE;
  504. }
  505.  
  506. ///////////////////////////////////////////////////////////////////////////
  507. //
  508. // disk test
  509. //
  510. ///////////////////////////////////////////////////////////////////////////
  511.  
  512. class DiskTestParameters {
  513. public:
  514.     LONG lFrameSize;
  515.     LONG lFrameCount;
  516.     LONG lFrameBuffers;
  517.     LONG lFrameRate;
  518.     LONG lDiskBuffer;
  519.     LONG lMicroSecPerFrame;
  520.     DWORD dwBufferMode;
  521. };
  522.  
  523. BOOL DiskTestCreateStruc(HWND hDlg, DiskTestParameters *dtp) {
  524.     BOOL fSuccess;
  525.     char buf[128], c;
  526.     double d;
  527.     long lWidth, lHeight, lDepth;
  528.  
  529.     SendMessage(GetDlgItem(hDlg, IDC_FRAME_SIZE), WM_GETTEXT, sizeof buf, (LPARAM)buf);
  530.  
  531.     ////
  532.  
  533.     if (3==sscanf(buf, "%ldx%ldx%ld", &lWidth, &lHeight, &lDepth))
  534.         dtp->lFrameSize = (lWidth*lDepth+31)/32 * 4 * lHeight;
  535.  
  536.     else if (2==sscanf(buf, "%ldx%ld", &lWidth, &lHeight))
  537.         dtp->lFrameSize = (lWidth+(lWidth&1))*lHeight*2;
  538.  
  539.     else if (2==sscanf(buf, "%ld%c", &lWidth, &c) && c=='k' || c=='K')
  540.         dtp->lFrameSize = lWidth*1024;        // kilobytes
  541.  
  542.     else if (1==sscanf(buf, "%ld", &lWidth))
  543.         dtp->lFrameSize = lWidth;        // well, bytes actually...
  544.  
  545.     ////
  546.  
  547.     if (dtp->lFrameSize < 16 || dtp->lFrameSize > 1048576) {
  548.         return FALSE;
  549.     }
  550.  
  551.     dtp->lFrameCount        = GetDlgItemInt(hDlg, IDC_FRAME_COUNT, &fSuccess, FALSE);
  552.     if (dtp->lFrameCount < 1 || dtp->lFrameCount > 89478400) {
  553.         return FALSE;
  554.     }
  555.  
  556.     dtp->lFrameBuffers    = GetDlgItemInt(hDlg, IDC_FRAME_BUFFERS, &fSuccess, FALSE);
  557.     if (dtp->lFrameBuffers < 16 || dtp->lFrameBuffers > 4096) {
  558.         return FALSE;
  559.     }
  560.  
  561.     dtp->lDiskBuffer        = GetDlgItemInt(hDlg, IDC_DISK_BUFFER, &fSuccess, FALSE);
  562.     if (dtp->lDiskBuffer < 64) {
  563.         return FALSE;
  564.     }
  565.  
  566.     SendMessage(GetDlgItem(hDlg, IDC_FRAME_RATE), WM_GETTEXT, sizeof buf, (LPARAM)buf);
  567.     if (1!=sscanf(buf, "%lf", &d) || d<0.01 || d>200.0) {
  568.         return FALSE;
  569.     }
  570.  
  571.     dtp->lMicroSecPerFrame = (1000000.0 / d) + 0.5;
  572.  
  573.     dtp->dwBufferMode = 0;
  574.     if (IsDlgButtonChecked(hDlg, IDC_DISABLE_BUFFERING))
  575.         dtp->dwBufferMode = FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING;
  576.  
  577.     return TRUE;
  578. }
  579.  
  580. /////////////////
  581.  
  582. LONG buffers;
  583. LONG buffers_in_use;
  584. long drop_count;
  585. long burst_drop_count;
  586. long max_burst_drop_count;
  587. BOOL last_was_dropped;
  588. volatile long captured_frames;
  589.  
  590. void CALLBACK DiskTestTimerProc(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) {
  591.     if (buffers_in_use >= buffers) {
  592.         ++drop_count;
  593.  
  594.         if (!last_was_dropped) {
  595.             burst_drop_count = 0;
  596.         }
  597.  
  598.         ++burst_drop_count;
  599.         last_was_dropped = TRUE;
  600.     } else {
  601.         if (burst_drop_count > max_burst_drop_count)
  602.             max_burst_drop_count = burst_drop_count;
  603.  
  604.         InterlockedIncrement(&buffers_in_use);
  605.  
  606.         last_was_dropped = FALSE;
  607.     }
  608.  
  609.     ++captured_frames;
  610. }
  611.  
  612. BOOL APIENTRY DiskTestStatusDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
  613.     switch(msg) {
  614.     case WM_INITDIALOG:
  615.         return TRUE;
  616.  
  617.     case WM_COMMAND:
  618.         switch(LOWORD(wParam)) {
  619.         case IDCANCEL:
  620.             PostQuitMessage(0);
  621.             return TRUE;
  622.         }
  623.         break;
  624.     }
  625.     return FALSE;
  626. }
  627.  
  628. void DiskTestDoIt(HWND hDlg) {
  629.     DiskTestParameters dtp;
  630.     char szFileName[MAX_PATH];
  631.     char szErrorBuf[MAX_PATH];
  632.     HMMIO hmmio        = NULL;
  633.     UINT timerID    = 0;
  634.     HANDLE hFile    = INVALID_HANDLE_VALUE;
  635.     HWND hwndStatus = NULL;
  636.     char *framebuf    = NULL;
  637.     char *buffer    = NULL;
  638.     int drive;
  639.  
  640.     if (CB_ERR == (drive = SendDlgItemMessage(hDlg, IDC_DRIVE, CB_GETCURSEL, 0, 0)))
  641.         return;
  642.  
  643.     drive = SendDlgItemMessage(hDlg, IDC_DRIVE, CB_GETITEMDATA, drive, 0);
  644.     sprintf(szFileName,"%c:\\DISKTEST.BIN", drive+'A');
  645.  
  646.     if (!DiskTestCreateStruc(hDlg, &dtp)) return;
  647.  
  648.     dtp.lFrameSize += 8;
  649.  
  650.     try {
  651.         DWORD max_frames;
  652.         MMIOINFO mmioinfo;
  653.         BOOL updated = FALSE;
  654.         long max_buffer_point = 0;
  655.         LONG lTotalBytes=0;
  656.         HWND hwndFrameCount, hwndDropCount, hwndBurstCount, hwndMaxBuffers;
  657.         LONG perthousand;
  658.         LONG tsec;
  659.         MSG msg;
  660.         DWORD dwOpenMode;
  661.  
  662.         if (!(hwndStatus = CreateDialog(g_hInst, MAKEINTRESOURCE(IDD_DISKTEST), hDlg, (DLGPROC)DiskTestStatusDlgProc)))
  663.             throw "Umm, no status dialog.  Doh!";
  664.  
  665.         EnableWindow(hDlg, FALSE);
  666.  
  667.         hwndFrameCount    = GetDlgItem(hwndStatus, IDC_FRAMES);
  668.         hwndDropCount    = GetDlgItem(hwndStatus, IDC_DROPPED);
  669.         hwndBurstCount    = GetDlgItem(hwndStatus, IDC_BURST_DROP);
  670.         hwndMaxBuffers    = GetDlgItem(hwndStatus, IDC_MAX_BUFFERS);
  671.  
  672.         if (!(framebuf = (char *)malloc(dtp.lFrameSize)))
  673.             throw "Couldn't allocate frame buffer.";
  674.  
  675.         if (!(buffer = (char *)VirtualAlloc(NULL, dtp.lDiskBuffer*1024, MEM_COMMIT, PAGE_READWRITE)))
  676.             throw "Couldn't allocate disk buffer";
  677.  
  678.         SetPriorityClass((HANDLE)GetCurrentProcess(), HIGH_PRIORITY_CLASS);
  679.  
  680.         ///////////
  681.  
  682.         buffers = dtp.lFrameBuffers;
  683.         buffers_in_use = 0;
  684.         drop_count = 0;
  685.         burst_drop_count = max_burst_drop_count = 0;
  686.         last_was_dropped = FALSE;
  687.         captured_frames = 0;
  688.         max_frames = dtp.lFrameCount;
  689.  
  690.         ////////////
  691.  
  692.         dwOpenMode = CREATE_NEW;
  693.  
  694.         for(;;) {
  695.             char msgbuf[MAX_PATH + 64];
  696.  
  697.             hFile = CreateFile(
  698.                     szFileName,
  699.                     GENERIC_WRITE,
  700.                     0,
  701.                     NULL,
  702.                     dwOpenMode,
  703.                     FILE_ATTRIBUTE_NORMAL | dtp.dwBufferMode,
  704.                     NULL
  705.                     );
  706.  
  707.             if (hFile == INVALID_HANDLE_VALUE) {
  708.                 if (GetLastError() == ERROR_FILE_EXISTS) {
  709.                     sprintf(msgbuf, "File %s already exists.  Overwrite?", szFileName);
  710.                     if (IDYES != MessageBox(hDlg, msgbuf, "Disk test warning", MB_YESNO))
  711.                         throw NULL;
  712.  
  713.                     dwOpenMode = OPEN_ALWAYS;
  714.                 } else {
  715.                     strcpy(szErrorBuf, "Error opening file: '");
  716.                     FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, szErrorBuf+22, (sizeof szErrorBuf)-22, NULL);
  717.                     strcat(szErrorBuf, "'");
  718.  
  719.                     throw szErrorBuf;
  720.                 }
  721.             } else
  722.                 break;
  723.  
  724.         }
  725.  
  726.         memset(&mmioinfo, 0, sizeof mmioinfo);
  727.         mmioinfo.fccIOProc    = FOURCC_DOS;
  728.         mmioinfo.cchBuffer    = dtp.lDiskBuffer*1024;
  729.         mmioinfo.pchBuffer    = buffer;
  730.         mmioinfo.adwInfo[0] = (DWORD)hFile;
  731.  
  732.         if (!(hmmio = mmioOpen(NULL, &mmioinfo, MMIO_WRITE /*| MMIO_ALLOCBUF*/)))
  733.             throw "Couldn't open test file.";
  734.  
  735.         if (!(timerID = timeSetEvent(
  736.                         (dtp.lMicroSecPerFrame+500)/1000,
  737.                         (dtp.lMicroSecPerFrame+500)/1000,
  738.                         DiskTestTimerProc,
  739.                         NULL,
  740.                         TIME_PERIODIC)))
  741.             throw "Unable to initialize timer.";
  742.  
  743.         while(captured_frames < max_frames) {
  744.             if (buffers_in_use) {
  745.                 updated = FALSE;
  746.  
  747.                 if (buffers_in_use > max_buffer_point) max_buffer_point = buffers_in_use;
  748.  
  749.                 if (dtp.lFrameSize != mmioWrite(hmmio, framebuf, dtp.lFrameSize))
  750.                     throw "I/O error";
  751.  
  752.                 lTotalBytes += dtp.lFrameSize;
  753.  
  754.                 InterlockedDecrement(&buffers_in_use);
  755.             } else {
  756.                 if (!updated) {
  757.                     updated = TRUE;
  758.                     PrintfWindowText(hwndFrameCount, "%d/%d ", captured_frames, dtp.lFrameCount);
  759.                     PrintfWindowText(hwndDropCount, "%d ", drop_count);
  760.                     PrintfWindowText(hwndBurstCount, "%d ", max_burst_drop_count);
  761.                     PrintfWindowText(hwndMaxBuffers, "%d/%d ", max_buffer_point, dtp.lFrameBuffers);
  762.                 }
  763.  
  764.                 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  765.                     if (msg.message == WM_QUIT)
  766.                         throw (char *)NULL;
  767.  
  768.                     if (!IsDialogMessage(hwndStatus, &msg) && !IsDialogMessage(hDlg, &msg)) {
  769.                         TranslateMessage(&msg);
  770.                         DispatchMessage(&msg);
  771.                     }
  772.                 }
  773.             }
  774.         }
  775.  
  776.         if (last_was_dropped)
  777.             if (burst_drop_count > max_burst_drop_count)
  778.                 max_burst_drop_count = burst_drop_count;
  779.  
  780.         // round out write to next 2048 bytes
  781.  
  782.         lTotalBytes = -lTotalBytes & 2047;
  783.  
  784.         if (lTotalBytes)
  785.             if (lTotalBytes != mmioWrite(hmmio, framebuf, lTotalBytes))
  786.                 throw "I/O error";
  787.  
  788.         ////////////
  789.  
  790.         if (!drop_count)
  791.             SetWindowText(hwndStatus, "Test passed - no frames dropped.");
  792.         else
  793.             SetWindowText(hwndStatus, "Test failed - frames were dropped.");
  794.  
  795.         SetDlgItemText(hwndStatus, IDCANCEL, "Ok");
  796.  
  797.         perthousand = (drop_count * 1000 + dtp.lFrameCount - 1) / dtp.lFrameCount;
  798.         tsec = (LONG)(((__int64)captured_frames * dtp.lMicroSecPerFrame + (__int64)99999) / 100000);
  799.  
  800.         PrintfWindowText(hwndFrameCount, "%d (%d.%d s)", captured_frames, tsec/10, tsec%10);
  801.         PrintfWindowText(hwndDropCount, "%d (%d.%d%%)", drop_count, perthousand/10, perthousand%10);
  802.         PrintfWindowText(hwndBurstCount, "%d (%d ms)", max_burst_drop_count,
  803.                 MulDiv(max_burst_drop_count, dtp.lMicroSecPerFrame, 1000));
  804.         PrintfWindowText(hwndMaxBuffers, "%d/%d ", max_buffer_point, dtp.lFrameBuffers);
  805.  
  806.         while (GetMessage(&msg, NULL, 0, 0)) {
  807.             if (!IsDialogMessage(hwndStatus, &msg) && !IsDialogMessage(hDlg, &msg)) {
  808.                 TranslateMessage(&msg);
  809.                 DispatchMessage(&msg);
  810.             }
  811.         }
  812.  
  813.     } catch(char *s) {
  814.         if (s)
  815.             MessageBox(hDlg, s, "Disk Test Error", MB_OK | MB_ICONEXCLAMATION);
  816.     }
  817.  
  818.     SetPriorityClass((HANDLE)GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
  819.     if (timerID) timeKillEvent(timerID); timerID = 0;
  820.     if (hmmio) mmioClose(hmmio,MMIO_FHOPEN);
  821.     if (hFile != INVALID_HANDLE_VALUE) {
  822.         CloseHandle(hFile);
  823.         DeleteFile(szFileName);
  824.     }
  825.     if (buffer) VirtualFree(buffer, 0, MEM_RELEASE);
  826.     if (framebuf) free(framebuf);
  827.     if (hwndStatus) {
  828.         EnableWindow(hDlg, TRUE);
  829.         SetFocus(hDlg);
  830.         DestroyWindow(hwndStatus);
  831.     }
  832. }
  833.  
  834. void DiskTestDoIt2(HWND hDlg) {
  835.     char szFileName[MAX_PATH];
  836.     char szErrorBuf[MAX_PATH];
  837.     UINT timerID    = 0;
  838.     HANDLE hFile    = INVALID_HANDLE_VALUE;
  839.     HWND hwndStatus = NULL;
  840.     char *buffer    = NULL;
  841.     int drive;
  842.     long lDiskBuffer, lMaxBytes;
  843.     BOOL fSuccess;
  844.     DWORD dwBufferMode;
  845.  
  846.     if (CB_ERR == (drive = SendDlgItemMessage(hDlg, IDC_DRIVE, CB_GETCURSEL, 0, 0)))
  847.         return;
  848.  
  849.     drive = SendDlgItemMessage(hDlg, IDC_DRIVE, CB_GETITEMDATA, drive, 0);
  850.     sprintf(szFileName,"%c:\\DISKTEST.BIN", drive+'A');
  851.  
  852.     lDiskBuffer        = GetDlgItemInt(hDlg, IDC_DISK_BUFFER, &fSuccess, FALSE);
  853.     if (lDiskBuffer < 64)
  854.         lDiskBuffer = 64;
  855.  
  856.     lDiskBuffer <<= 10;
  857.  
  858.     lMaxBytes        = GetDlgItemInt(hDlg, IDC_TOTAL_SIZE, &fSuccess, FALSE);
  859.     lMaxBytes <<= 20;
  860.  
  861.     dwBufferMode = 0;
  862.     if (IsDlgButtonChecked(hDlg, IDC_DISABLE_BUFFERING))
  863.         dwBufferMode = FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING;
  864.  
  865.     try {
  866.         LONG lTotalBytes=0;
  867.         MSG msg;
  868.         DWORD dwOpenMode;
  869.         DWORD dwReadTimeStart, dwReadTimeEnd, dwWriteTimeStart, dwWriteTimeEnd;
  870.  
  871.         if (!(hwndStatus = CreateDialog(g_hInst, MAKEINTRESOURCE(IDD_DISKTEST2), hDlg, (DLGPROC)DiskTestStatusDlgProc)))
  872.             throw "Umm, no status dialog.  Doh!";
  873.  
  874.         EnableWindow(hDlg, FALSE);
  875.  
  876.         if (!(buffer = (char *)VirtualAlloc(NULL, lDiskBuffer, MEM_COMMIT, PAGE_READWRITE)))
  877.             throw "Couldn't allocate disk buffer";
  878.  
  879.         SetPriorityClass((HANDLE)GetCurrentProcess(), HIGH_PRIORITY_CLASS);
  880.  
  881.         ////////////
  882.  
  883.         dwOpenMode = CREATE_NEW;
  884.  
  885.         for(;;) {
  886.             char msgbuf[MAX_PATH + 64];
  887.  
  888.             hFile = CreateFile(
  889.                     szFileName,
  890.                     GENERIC_READ | GENERIC_WRITE,
  891.                     0,
  892.                     NULL,
  893.                     dwOpenMode,
  894.                     FILE_ATTRIBUTE_NORMAL | dwBufferMode,
  895.                     NULL
  896.                     );
  897.  
  898.             if (hFile == INVALID_HANDLE_VALUE) {
  899.                 if (GetLastError() == ERROR_FILE_EXISTS) {
  900.                     sprintf(msgbuf, "File %s already exists.  Overwrite?", szFileName);
  901.                     if (IDYES != MessageBox(hDlg, msgbuf, "Disk test warning", MB_YESNO))
  902.                         throw NULL;
  903.  
  904.                     dwOpenMode = OPEN_ALWAYS;
  905.                 } else {
  906.                     strcpy(szErrorBuf, "Error opening file: '");
  907.                     FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, szErrorBuf+22, (sizeof szErrorBuf)-22, NULL);
  908.                     strcat(szErrorBuf, "'");
  909.  
  910.                     throw szErrorBuf;
  911.                 }
  912.             } else
  913.                 break;
  914.  
  915.         }
  916.  
  917.         while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  918.             if (msg.message == WM_QUIT)
  919.                 throw (char *)NULL;
  920.  
  921.             if (!IsDialogMessage(hwndStatus, &msg) && !IsDialogMessage(hDlg, &msg)) {
  922.                 TranslateMessage(&msg);
  923.                 DispatchMessage(&msg);
  924.             }
  925.         }
  926.  
  927.         SetWindowText(hwndStatus, "Prewriting file...");
  928.         while(lTotalBytes < lMaxBytes) {
  929.             DWORD dwBytes = lMaxBytes - lTotalBytes;
  930.             DWORD dwActual;
  931.  
  932.             if (dwBytes > lDiskBuffer)
  933.                 dwBytes = lDiskBuffer;
  934.  
  935.             if (!WriteFile(hFile, buffer, dwBytes, &dwActual, NULL) || dwActual != dwBytes)
  936.                 throw "I/O error";
  937.  
  938.             lTotalBytes += dwBytes;
  939.         }
  940.         FlushFileBuffers(hFile);
  941.  
  942.         SetWindowText(hwndStatus, "Writing to file...");
  943.         SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
  944.         FlushFileBuffers(hFile);
  945.  
  946.         dwWriteTimeStart = GetTickCount();
  947.         lTotalBytes=0;
  948.         while(lTotalBytes < lMaxBytes) {
  949.             DWORD dwBytes = lMaxBytes - lTotalBytes;
  950.             DWORD dwActual;
  951.  
  952.             if (dwBytes > lDiskBuffer)
  953.                 dwBytes = lDiskBuffer;
  954.  
  955.             if (!WriteFile(hFile, buffer, dwBytes, &dwActual, NULL) || dwActual != dwBytes)
  956.                 throw "I/O error";
  957.  
  958.             lTotalBytes += dwBytes;
  959.         }
  960.         FlushFileBuffers(hFile);
  961.         dwWriteTimeEnd = GetTickCount();
  962.  
  963.         SetWindowText(hwndStatus, "Reading from file...");
  964.  
  965.         SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
  966.         FlushFileBuffers(hFile);
  967.  
  968.         dwReadTimeStart = GetTickCount();
  969.         lTotalBytes=0;
  970.         while(lTotalBytes < lMaxBytes) {
  971.             DWORD dwBytes = lMaxBytes - lTotalBytes, dwActual;
  972.  
  973.             if (dwBytes > lDiskBuffer)
  974.                 dwBytes = lDiskBuffer;
  975.  
  976.             if (!ReadFile(hFile, buffer, dwBytes, &dwActual, NULL) || dwActual != dwBytes)
  977.                 throw "I/O error";
  978.  
  979.             lTotalBytes += dwBytes;
  980.         }
  981.         FlushFileBuffers(hFile);
  982.         dwReadTimeEnd = GetTickCount();
  983.  
  984.         ////////////
  985.         HWND hwndWrite, hwndRead;
  986.  
  987.         SetWindowText(hwndStatus, "Test complete.");
  988.  
  989.         SetDlgItemText(hwndStatus, IDCANCEL, "Ok");
  990.  
  991.         hwndRead = GetDlgItem(hwndStatus, IDC_READ_SPEED);
  992.         hwndWrite = GetDlgItem(hwndStatus, IDC_WRITE_SPEED);
  993.  
  994.         if (dwReadTimeStart == dwReadTimeEnd)
  995.             SetWindowText(hwndRead, "(too fast to measure)");
  996.         else
  997.             PrintfWindowText(hwndRead , "%ld K/s ", MulDiv(lMaxBytes>>10, 1000, dwReadTimeEnd-dwReadTimeStart));
  998.  
  999.         if (dwWriteTimeStart == dwWriteTimeEnd)
  1000.             SetWindowText(hwndRead, "(too fast to measure)");
  1001.         else
  1002.             PrintfWindowText(hwndWrite, "%ld K/s ", MulDiv(lMaxBytes>>10, 1000, dwWriteTimeEnd-dwWriteTimeStart));
  1003.  
  1004.         while (GetMessage(&msg, NULL, 0, 0)) {
  1005.             if (!IsDialogMessage(hwndStatus, &msg) && !IsDialogMessage(hDlg, &msg)) {
  1006.                 TranslateMessage(&msg);
  1007.                 DispatchMessage(&msg);
  1008.             }
  1009.         }
  1010.  
  1011.     } catch(char *s) {
  1012.         if (s)
  1013.             MessageBox(hDlg, s, "Disk Test Error", MB_OK | MB_ICONEXCLAMATION);
  1014.     }
  1015.  
  1016.     SetPriorityClass((HANDLE)GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
  1017.     if (hFile != INVALID_HANDLE_VALUE) {
  1018.         CloseHandle(hFile);
  1019.         DeleteFile(szFileName);
  1020.     }
  1021.     if (buffer) VirtualFree(buffer, 0, MEM_RELEASE);
  1022.     if (hwndStatus) {
  1023.         EnableWindow(hDlg, TRUE);
  1024.         SetFocus(hDlg);
  1025.         DestroyWindow(hwndStatus);
  1026.     }
  1027. }
  1028.  
  1029. ///////////////////////////////////////////////////
  1030.  
  1031. DWORD dwDiskTestInitDlgHelpLookup[]={
  1032.     IDC_FRAME_SIZE,                IDH_BENCHMARK_FRAME_SIZE,
  1033.     IDC_FRAME_COUNT,            IDH_BENCHMARK_FRAME_COUNT,
  1034.     IDC_FRAME_BUFFERS,            IDH_BENCHMARK_FRAME_BUFFERS,
  1035.     IDC_FRAME_RATE,                IDH_BENCHMARK_FRAME_RATE,
  1036.     IDC_DISK_BUFFER,            IDH_BENCHMARK_DISK_BUFFER,
  1037.     IDC_DATA_RATE,                IDH_BENCHMARK_DATA_RATE,
  1038.     IDC_BUFFERING_NONE,            IDH_BENCHMARK_BUFFERING,
  1039.     IDC_BUFFERING_COMBINEONLY,    IDH_BENCHMARK_BUFFERING,
  1040.     IDC_BUFFERING_FULL,            IDH_BENCHMARK_BUFFERING,
  1041.     0,
  1042. };
  1043.  
  1044. void DiskTestUpdateFields(HWND hDlg) {
  1045.     DiskTestParameters dtp;
  1046.  
  1047.     if (!DiskTestCreateStruc(hDlg, &dtp))
  1048.         SetDlgItemText(hDlg, IDC_DATA_RATE, "<unknown>");
  1049.     else
  1050.         SetDlgItemInt(hDlg, IDC_DATA_RATE,(LONG)(
  1051.             (((__int64)dtp.lFrameSize * 1000000 + dtp.lMicroSecPerFrame/2) / dtp.lMicroSecPerFrame + 1023) / 1024),
  1052.             FALSE);
  1053. }
  1054.  
  1055. void DiskTestInitDlg(HWND hDlg) {
  1056.     DWORD dwDriveMask = GetLogicalDrives();
  1057.     HWND hwndCombo = GetDlgItem(hDlg, IDC_DRIVE);
  1058.     char buf[256], szVolName[64];
  1059.     int i;
  1060.     BOOL fHaveSelection = FALSE;
  1061.  
  1062.     for(i=0; i<26; i++) {
  1063.         if (dwDriveMask & (1L<<i)) {
  1064.             UINT uiDriveType;
  1065.             char *lpszDesc;
  1066.             char *s;
  1067.             int index;
  1068.  
  1069.             sprintf(buf, "%c:\\", i+'A');
  1070.             uiDriveType = GetDriveType(buf);
  1071.  
  1072.             switch(uiDriveType) {
  1073.             case 1:                    continue;    // no root directory!?
  1074.             case DRIVE_CDROM:        continue;    // How do you capture to a CD-ROM?
  1075.             case DRIVE_REMOVABLE:    lpszDesc = "Removable disk";    break;
  1076.             case DRIVE_FIXED:        lpszDesc = "Hard disk";            break;
  1077.             case DRIVE_REMOTE:        lpszDesc = "Network drive";        break;
  1078.             case DRIVE_RAMDISK:        lpszDesc = "Ramdisk";            break;
  1079.             default:                lpszDesc = "";                    break;
  1080.             }
  1081.  
  1082.             if (uiDriveType==DRIVE_FIXED && GetVolumeInformation(buf, szVolName, sizeof szVolName, NULL, NULL, NULL, NULL, 0))
  1083.                 sprintf(buf, "%c: %s [%s]", i+'A', lpszDesc, szVolName);
  1084.             else
  1085.                 sprintf(buf, "%c: %s", i+'A', lpszDesc);
  1086.  
  1087.             index = SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM)buf);
  1088.  
  1089.             if (index != CB_ERR) {
  1090.                 SendMessage(hwndCombo, CB_SETITEMDATA, (WPARAM)index, i);
  1091.                 if (!fHaveSelection && (i>=2 || !(dwDriveMask>>(i+1)))) {
  1092.                     fHaveSelection = TRUE;
  1093.  
  1094.                     SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM)index, 0);
  1095.                 }
  1096.             }
  1097.         }
  1098.     }
  1099.  
  1100.     SetDlgItemText(hDlg, IDC_FRAME_SIZE, "320x240x16");
  1101.     SetDlgItemText(hDlg, IDC_FRAME_COUNT, "200");
  1102.     SetDlgItemText(hDlg, IDC_FRAME_BUFFERS, "50");
  1103.     SetDlgItemText(hDlg, IDC_FRAME_RATE, "15.000");
  1104.     SetDlgItemText(hDlg, IDC_DISK_BUFFER, "1024");
  1105.     SetDlgItemText(hDlg, IDC_TOTAL_SIZE, "50");
  1106.     DiskTestUpdateFields(hDlg);
  1107.  
  1108.     CheckDlgButton(hDlg, IDC_BUFFERING_NONE, BST_CHECKED);
  1109. }
  1110.  
  1111. BOOL APIENTRY DiskTestDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
  1112.     switch(msg) {
  1113.         case WM_INITDIALOG:
  1114.             DiskTestInitDlg(hDlg);
  1115.             return TRUE;
  1116.  
  1117.         case WM_COMMAND:
  1118.             switch(LOWORD(wParam)) {
  1119.             case IDC_FRAME_SIZE:
  1120.             case IDC_FRAME_COUNT:
  1121.             case IDC_FRAME_BUFFERS:
  1122.             case IDC_FRAME_RATE:
  1123.             case IDC_DISK_BUFFER:
  1124.                 if (HIWORD(wParam)==EN_UPDATE)
  1125.                     DiskTestUpdateFields(hDlg);
  1126.                 break;
  1127.             case IDOK:
  1128.                 DiskTestDoIt(hDlg);
  1129.                 return TRUE;
  1130.             case IDC_BENCHDISK:
  1131.                 DiskTestDoIt2(hDlg);
  1132.                 return TRUE;
  1133.             case IDCANCEL:
  1134.                 EndDialog(hDlg, FALSE);
  1135.                 return TRUE;
  1136.             }
  1137.             break;
  1138.  
  1139.         case WM_HELP:
  1140.             {
  1141.                 HELPINFO *lphi = (HELPINFO *)lParam;
  1142.  
  1143.                 if (lphi->iContextType == HELPINFO_WINDOW)
  1144.                     HelpPopupByID(hDlg, lphi->iCtrlId, dwDiskTestInitDlgHelpLookup);
  1145.             }
  1146.             return TRUE;
  1147.     }
  1148.     return FALSE;
  1149. }
  1150.  
  1151. ///////////////////////////////////////////////////////////////////////////
  1152. //
  1153. //    About...
  1154. //
  1155. ///////////////////////////////////////////////////////////////////////////
  1156.  
  1157. BOOL APIENTRY AboutDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
  1158.     switch(msg) {
  1159.         case WM_INITDIALOG:
  1160.             SetDlgItemText(hDlg, IDC_FINALS_SUCK,
  1161. #ifdef _DEBUG
  1162.                 "Debug build"
  1163. #else
  1164.                 "Release build"
  1165. #endif
  1166.                 " ("__DATE__" "__TIME__")");
  1167.  
  1168.             return TRUE;
  1169.  
  1170.         case WM_COMMAND:
  1171.             switch(LOWORD(wParam)) {
  1172.             case IDOK:
  1173.             case IDCANCEL:
  1174.                 EndDialog(hDlg, FALSE);
  1175.                 return TRUE;
  1176.             }
  1177.     }
  1178.     return FALSE;
  1179. }
  1180.